package player;

import helliker.id3.ID3v2FormatException;
import helliker.id3.MP3File;
import helliker.id3.Playlist;
import helliker.id3.PlaylistException;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
//nang
import java.io.BufferedReader;
//
import java.io.File;
//nang
import java.io.FileReader;
//
import java.io.IOException;
import java.net.MalformedURLException;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.EndOfMediaEvent;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoPlayerException;
import javax.media.Player;
import javax.media.PrefetchCompleteEvent;
import javax.media.RealizeCompleteEvent;
import javax.media.Time;
import javax.swing.BorderFactory;
import javax.swing.Box;
//Nang
import javax.swing.Icon;
//
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.JWindow;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.plaf.basic.BasicProgressBarUI;

/**
 * Player GUI + Open playlist + Open playlist manager + Support:
 * Play/Pause/Stop/Previous/Next function + Display progress and name of playing
 * song
 * 
 */
public class JavaPlayer extends JWindow implements ActionListener,
ControllerListener, MouseMotionListener,MouseListener, Runnable {
	private Playlist playlist;
	private Player player = null;
	private JPanel mainPanel = null;
	private JProgressBar progressBar = null;
	private String fileTitle = "";
	private Thread playThread = null;
	private JButton button;
	private JButton btnSound;
	private JSlider slider = new JSlider();
	private JLabel lblSound = new JLabel();
	private JLabel lblDevices = new JLabel("Set player sound volume:");
	
	private boolean isSound = true;
	private int DraggedX;
	private int DraggedY;
	
	private JButton btnShuffle = new JButton();
	private boolean isShuffle = false;

	// fix issue 85
	private static PlaylistManager manager ;
	//
	
	
	
	public JavaPlayer() {
		super();
		mainPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 1, 1));
		mainPanel.setBorder(BorderFactory.createRaisedBevelBorder());
		mainPanel.addMouseMotionListener(this);
		// Duy - defect use mouse to drag window
		mainPanel.addMouseListener(this);
		//
		Settings.loadSettings();
		setBounds(Settings.getMainWindowRect());
		buildToolbar();
		// Duy - Defect khong add mainPanel vao cua so
		add(mainPanel);
		//
		playlist = new Playlist();
		File playlistFile = new File(Settings.getPlaylistDirectory(),
				Settings.getPlaylistFile());
		if (playlistFile.exists() && playlistFile.isFile()) {
			progressBar.setString("Loading Playlist...");
			try {
				playlist.loadFromFile(playlistFile);
			} catch (IOException ex) {
				errorMessage(ex.getMessage());
			} catch (PlaylistException ex) {
				errorMessage(ex.getMessage());
			}
			progressBar.setString("");
		}
		// Duy - Defect khong hien len cua so
		setVisible(true);
		//
		
		// fix issue 89
		slider.setValue((int)(Settings.getSoundVolume()*100));
		//
	}

	/**
	 * build Player User Interface (GUI)
	 */
	private void buildToolbar() {
		button = new JButton(new ImageIcon(getClass().getClassLoader()
				.getResource("icons/Playlist16.png")));
		button.setPreferredSize(new Dimension(20, 20));
		button.setActionCommand("Open Playlist");
		button.addActionListener(this);

		mainPanel.add(button);
		button = new JButton(new ImageIcon(getClass().getClassLoader()
				.getResource("icons/Manager116.png")));
		// Duy - Defect nut qua lon
		button.setPreferredSize(new Dimension(20, 20));
		//
		button.setActionCommand("Playlist Manager");
		button.addActionListener(this);

		mainPanel.add(button);
		button = new JButton(new ImageIcon(getClass().getClassLoader()
				.getResource("icons/Play16.png")));
		button.setPreferredSize(new Dimension(20, 20));
		button.setActionCommand("Play");
		button.addActionListener(this);
		mainPanel.add(button);
		button = new JButton(new ImageIcon(getClass().getClassLoader()
				.getResource("icons/Pause16.png")));
		button.setPreferredSize(new Dimension(20, 20));
		button.setActionCommand("Pause");
		button.addActionListener(this);

		mainPanel.add(button);
		button = new JButton(new ImageIcon(getClass().getClassLoader()
				.getResource("icons/Stop16.png")));
		button.setPreferredSize(new Dimension(20, 20));
		button.setActionCommand("Stop");
		button.addActionListener(this);

		mainPanel.add(button);
		button = new JButton(new ImageIcon(getClass().getClassLoader()
				.getResource("icons/Previous16.png")));
		button.setPreferredSize(new Dimension(20, 20));
		// Duy - Defect chuc nang nut previous khong hoat dong
		button.setActionCommand("Previous");
		//
		button.addActionListener(this);

		mainPanel.add(button);
		button = new JButton(new ImageIcon(getClass().getClassLoader()
				.getResource("icons/Next16.png")));
		button.setPreferredSize(new Dimension(20, 20));
		// Duy - Defect chuc nang nut next khong hoat dong
		button.setActionCommand("Next");
		button.addActionListener(this);
		mainPanel.add(button);
		//
		
		// Duy - them button shuffle cho player
				btnShuffle = new JButton(new ImageIcon(getClass().getClassLoader()
						.getResource("icons/Shuffle16.png")));
				btnShuffle.setPreferredSize(new Dimension(20, 20));
				btnShuffle.setActionCommand("Shuffle");
				btnShuffle.addActionListener(new ActionListener() {
					
					public void actionPerformed(ActionEvent arg0) {
						// TODO Auto-generated method stub
						if(isShuffle) {
							btnShuffle.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/Shuffle16.png")));
							Settings.setSoundVolume(player.getGainControl().getLevel());
							isShuffle = false;
						} else {
							btnShuffle.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/ShuffleON16.png")));
							isShuffle = true;
						}
					}
				});
				mainPanel.add(btnShuffle);
		//
				
		mainPanel.add(Box.createHorizontalStrut(2));
		progressBar = new JProgressBar();
		progressBar.setPreferredSize(new Dimension(270, 18));
		progressBar.setStringPainted(true);
		progressBar.setFont(new Font("Dialog", Font.BOLD, 10));
		progressBar.setString("");

		mainPanel.add(progressBar);
		mainPanel.add(Box.createHorizontalStrut(2));
		button = new JButton(new ImageIcon(getClass().getClassLoader()
				.getResource("icons/Exit16.png")));
		button.setPreferredSize(new Dimension(20, 20));
		button.setActionCommand("Exit");
		button.addActionListener(this);
		// Nang - Defect khong co nut exit
		mainPanel.add(button);
		//
		
		// label sound
		lblDevices.setPreferredSize(new Dimension(145,20));
		lblDevices.setForeground(Color.blue);
		lblDevices.setFont(new Font("Arial",Font.HANGING_BASELINE,12));
		mainPanel.add(lblDevices);
		//
		
		//nut mute
		btnSound = new JButton(new ImageIcon(getClass().getClassLoader().getResource("icons/Speaker16.png")));
		btnSound.setPreferredSize(new Dimension(20, 20));
		btnSound.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				if(isSound) {
					btnSound.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/Speaker_mute16.png")));
					isSound=false;
					slider.setValue(0);
					player.getGainControl().setMute(true);
				} else {
					btnSound.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/Speaker16.png")));
					isSound=true;
					player.getGainControl().setMute(false);
					slider.setValue(100);
				}
				
			}
			
		});
		mainPanel.add(btnSound);
		//
		// slider, volume
		slider.setPreferredSize(new Dimension(280,20));
		slider.addChangeListener(new ChangeListener() {

			public void stateChanged(ChangeEvent arg0) {
				// TODO Auto-generated method stub
				if(player!=null) {
					player.getGainControl().setLevel((float)slider.getValue()/100);
					Settings.setSoundVolume(player.getGainControl().getLevel());
					if(player.getGainControl().getLevel()==0) {
						btnSound.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/Speaker_mute16.png")));
					} else {
						btnSound.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/Speaker16.png")));
					}
				}			
			}
			
		});
		mainPanel.add(slider);
		//
	}

	/**
	 * Show error message
	 * 
	 * @param s
	 *            : error message
	 */
	public void errorMessage(String s) {
		// Duy - issue 84 sua loi thong bao hien information thay vi error
		JOptionPane.showMessageDialog(null, "Invalid mp3 file", "Error",
				JOptionPane.ERROR_MESSAGE);
		//
	}

	/**
	 * Exit Application
	 */
	private void exitAction() {
		Settings.setMainWindowRect(getBounds());
		Settings.storeSettings();
		if (player != null) {
			player.removeControllerListener(this);
			player.stop();
			player.close();
			player = null;
		}
		if (playThread == null) {
			playThread = null;
		}
		// Nang - Defect nut exit khong hoat dong
		System.exit(0);
		//
	}

	/**
	 * Show Playlist Manager Form
	 */
	private void managerAction() {
		// Duy issue 85
		if (playlist != null) {
			manager.setVisible(true);
		}
		//
	}

	/**
	 * Open existed playlist file (m3u...)
	 */
	// Duy change private thanh public
	public void playlistAction() {
		//
		JFileChooser fileChooser = new JFileChooser(
				Settings.getPlaylistDirectory());
		fileChooser.setMultiSelectionEnabled(true);
		// Duy - Defect nen de filter playlistfile thanh mac dinh thay vi
		// allfiles
		fileChooser.setAcceptAllFileFilterUsed(false);
		fileChooser.addChoosableFileFilter(new PlaylistFilter());
		fileChooser.setAcceptAllFileFilterUsed(true);
		//

		if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
			progressBar.setString("Loading Playlist...");
			playlist = new Playlist();
			try {
				File playlistFile = fileChooser.getSelectedFile();
				playlist.loadFromFile(playlistFile);
				Settings.setPlaylistDirectory(playlistFile.getParent());
				Settings.setPlaylistFile(playlistFile.getName());
			} catch (IOException ex) {
				errorMessage(ex.getMessage());
			} catch (PlaylistException ex) {
				errorMessage(ex.getMessage());
			}
			progressBar.setString("");
			this.setVisible(false);
		}
		// Duy - Defect thieu xu ly khi khong chon file
		
		//
	}

	public Playlist getPlaylist() {
		return playlist;
	}

	public void setPlaylist(Playlist p) {
		playlist = p;
	}

	public Player getPlayer() {
		return player;
	}

	/**
	 * Play current song in playlist
	 */
	public void play() {
		MP3File mp3File = null;
		int position = Settings.getPlaylistPosition();

		try {
			mp3File = (MP3File) playlist.get(position);

			fileTitle = mp3File.getTitle();
		} catch (ID3v2FormatException ex) {
			errorMessage(ex.getMessage());
		}
		if (player == null) {
			try {
				File file = new File(mp3File.getPath());
				MediaLocator mediaLocator = new MediaLocator(file.toURL());
				player = Manager.createPlayer(mediaLocator);
				player.addControllerListener(this);
				progressBar.setString("Realizing...");
				player.realize();
			} catch (MalformedURLException ex) {
				errorMessage(ex.getMessage());
			} catch (NoPlayerException ex) {
				errorMessage(ex.getMessage());
			} catch (IOException ex) {
				errorMessage(ex.getMessage());
			}
		} else {
			player.start();
			progressBar.setString("Playing...");
		}
	}

	/**
	 * Pause playing song
	 */
	private void pause() {
		if (player != null) {

			MP3File mp3File = null;
			int position = Settings.getPlaylistPosition();

			try {
				mp3File = (MP3File) playlist.get(position);

				fileTitle = mp3File.getTitle();

				progressBar.setString(fileTitle + " Paused");
			} catch (ID3v2FormatException ex) {
				errorMessage(ex.getMessage());
			}

			player.stop();

		}

	}

	/**
	 * Stop playing song
	 */
	public void stop() {
		if (player != null) {
			player.removeControllerListener(this);
			player.stop();
			player.close();
			player = null;
		}
		if (playThread != null) {
			playThread = null;
		}
		progressBar.setValue(0);
		progressBar.setString("");
	}

	/**
	 * Play previous song in playlist
	 */
	private void previous() {
		PlaylistManager manager = new PlaylistManager(this);	
		int position = Settings.getPlaylistPosition();
		if(position == 0) {
			position=manager.getNumberOfSong();
		}
		position--;		
		Settings.setPlaylistPosition(position);
		if (player != null)
			stop();
		play();
	}

	/**
	 * Play next song in playlist
	 */
	private void next() {
		PlaylistManager manager = new PlaylistManager(this);		
		int position = Settings.getPlaylistPosition();
		position++;
		if(position == manager.getNumberOfSong()) {
			position=0;
		}
		Settings.setPlaylistPosition(position);
		//Duy - chuc nang cho nut shuffle
		if(isShuffle) {
			Settings.setPlaylistPosition((int)(Math.random()*manager.getNumberOfSong()));
		}
		//
		if (player != null)
			stop();
		play();
	}

	public static void main(String args[]) {
		JavaPlayer jplayer= new JavaPlayer();
		manager = new PlaylistManager(jplayer);
	}

	public void actionPerformed(ActionEvent ev) {
		JButton button = (JButton) ev.getSource();
		String command = button.getActionCommand();
		if (command.equals("Exit"))
			exitAction();
		else if (command.equals("Open Playlist"))
			playlistAction();
		else if (command.equals("Playlist Manager"))
			managerAction();
		else if (command.equals("Play"))
			play();
		else if (command.equals("Pause"))
			pause();
		else if (command.equals("Stop"))
			stop();
		else if (command.equals("Previous"))
			previous();
		else if (command.equals("Next"))
			next();
		// Duy issue khong doi mau khi doi bai nhac
		manager.repaint();
		//
	}

	// Update GUI base on Event object
	public void controllerUpdate(ControllerEvent ev) {
		if (ev instanceof RealizeCompleteEvent) {
			player.prefetch();
			progressBar.setString("Prefetching...");
		}
		if (ev instanceof PrefetchCompleteEvent) {
			Time time = player.getDuration();
			progressBar.setMaximum((int) time.getSeconds());
			progressBar.setString("Playing " + fileTitle);
			playThread = new Thread(this);
			playThread.start();
			player.getGainControl().setLevel(1);
			player.start();
			manager.repaint();
			player.getGainControl().setLevel(Settings.getSoundVolume());
		}
		if (ev instanceof EndOfMediaEvent) {
			player.removeControllerListener(this);
			player.stop();
			player.close();
			player = null;
			if (playThread != null) {
				playThread = null;
			}
			progressBar.setValue(0);
			next();
		}
	}

	/**
	 * Catch mouse position to move the GUI
	 */
	public void mouseDragged(MouseEvent ev) {
		Point loc = getLocation();
		Point clk = ev.getPoint();
		Point pt = new Point(loc.x + clk.x-DraggedX, loc.y + clk.y-DraggedY);
		setLocation(pt);
	}

	public void mouseMoved(MouseEvent ev) {
	}

	/**
	 * Update Progress bar base on played time
	 */
	public void run() {
		//Duy sua
				int second;
				int minutes = 0;
				int maxSecond;
				int maxMinute;
				int secondDuration;
				int minuteDuration=0;

				while (playThread != null) {
					if (player != null) {
						progressBar.setUI(new BasicProgressBarUI() {

							@Override
							protected Color getSelectionBackground() {
								// TODO Auto-generated method stub
								Color c= super.getSelectionBackground();
								return c.blue ;
							}

							@Override
							protected Color getSelectionForeground() {
								// TODO Auto-generated method stub
								return super.getSelectionForeground();
							}
						
						});
						// sua 500 thanh 1000 , 
						Time time = player.getMediaTime();
						Time time2 = player.getDuration();
						progressBar.setValue((int) time.getSeconds());

						/*second = (int) time.getSeconds()%60;	
						if((int)time.getSeconds()%60 ==0 && (int)time.getSeconds()!=0) {			
							minutes +=1;
						}
						if(second <10) {
							progressBar.setString("Playing "+fileTitle+"( " +minutes+":0"+second+" )");
						} else {
							progressBar.setString("Playing "+fileTitle+"( " +minutes+":"+second+" )");
						}
						 */

						//thoi gian dem nguoc
						maxSecond = (int) time2.getSeconds();
						second = (int) time.getSeconds();
						maxMinute = (int) time2.getSeconds() /60-minuteDuration;
						secondDuration = maxSecond - second;

						if(secondDuration %60 ==0 && secondDuration != maxSecond) {
							minuteDuration +=1;
						}
						if(secondDuration == maxSecond) {
							minuteDuration =0;
						}
						if(secondDuration%60 <10) {
							progressBar.setString("Playing "+fileTitle+"( " +maxMinute+":0"+secondDuration%60+" )");
						} else {
							progressBar.setString("Playing "+fileTitle+"( " +maxMinute+":"+secondDuration%60+" )");
						}
						//


						try {
							playThread.sleep(1000);
						} catch (InterruptedException ex) {
						}
					}
				}
			}

			/**
			 * Filter to open just *.m3u files
			 * 
			 */
			class PlaylistFilter extends FileFilter {
				public boolean accept(File file) {
					if (file.isDirectory())
						return true;
					String s = file.getName().toLowerCase();
					if (s.endsWith(".m3u"))
						return true;
					return false;
				}

				public String getDescription() {
					return "Playlist Files";
				}

			}

			public void mouseClicked(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			public void mouseEntered(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

			public void mouseExited(MouseEvent arg0) {
				// TODO Auto-generated method stub
			
			}

			public void mousePressed(MouseEvent arg0) {
				// TODO Auto-generated method stub
				DraggedX = arg0.getX();
		        DraggedY = arg0.getY();
			}

			public void mouseReleased(MouseEvent arg0) {
				// TODO Auto-generated method stub
				
			}

		}